package com.dingtalk.video.tools;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class UnionVideoUtils {

    private static final String ffmpegPath = "D:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe";
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {

        Long start = System.currentTimeMillis();
        String newfilePath = "D:\\study\\直播回放\\合并\\案例分析2.mp4";
        String outputDir = "D:\\study\\直播回放\\合并\\";

        String path = "D:\\study\\直播回放\\案例分析2";
        File file = new File(path);
        File[] files = file.listFiles();

        Map<Integer, File> sortMap = new HashMap<>();
        for (File f : files) {
            String key = f.getName().split("\\.")[0];
            sortMap.put(Integer.valueOf(key), f);
        }

        List<String> fromVideoFileList = new ArrayList();
        Integer[] keys = sortMap.keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        for (Integer key : keys) {
            fromVideoFileList.add(sortMap.get(key).getPath());
        }
        mergeVideo(fromVideoFileList, outputDir, newfilePath);
        System.out.println("mergeVideo execute time sec==>time:" + (System.currentTimeMillis() - start));
    }

    /**
     * ffmpeg合并多个视频文件
     *
     * @param list       需要合并的多视频url地址以List存放
     * @param outputDir  此处是ffmpeg 配置地址，可写死如“E:/ffmpeg/bin/ffmpeg.exe”
     * @param outputFile 合并后的视频存放地址，如：E:/mergevideo.mp4
     * @date: 2021/4/17 9:31
     * @return: void
     */
    public static String mergeVideo(List<String> list, String outputDir, String outputFile) {
        try {
            String format1 = "%s -i %s -c copy -bsf:v h264_mp4toannexb -f mpegts %s";
            List<String> commandList = new ArrayList<>(6);
            List<String> inputList = new ArrayList<>(6);
            for (int i = 0; i < list.size(); i++) {
                String input = String.format("input%d.ts", i + 1);
                String command = String.format(format1, ffmpegPath, list.get(i), outputDir + input);
                commandList.add(command);
                inputList.add(input);
            }
            String command = getCommand(outputDir, outputFile, inputList);
            commandList.add(command);
            Boolean falg = Boolean.FALSE;
            for (int i = 0; i < commandList.size(); i++) {
                if (execCommand(commandList.get(i)) > 0) {
                    falg = true;
                }
            }
            if (falg) {
                for (int i = 0; i < inputList.size(); i++) {
                    if (i != commandList.size() - 1) {
                        File file = new File(outputDir + inputList.get(i));
                        file.delete();
                    }
                }
                return outputFile;
            } else {
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("-----合并失败!!!!!!" + outputFile);
            return "fail";
        }

    }

    /**
     * 拼接执行新的videoUrl command命令
     *
     * @param outputFile
     * @param newfilePath
     * @param inputList
     * @date: 2021/4/17 11:29
     * @return: java.lang.StringBuffer
     */
    private static String getCommand(String outputFile, String newfilePath, List<String> inputList) {

        StringBuffer tsPath = new StringBuffer();
        tsPath.append(ffmpegPath);
        tsPath.append(" -i ");
        tsPath.append("\"");
        tsPath.append("concat:");
        for (int t = 0; t < inputList.size(); t++) {
            tsPath.append(outputFile);
            if (t != inputList.size() - 1) {
                tsPath.append(inputList.get(t) + "|");
            } else {
                tsPath.append(inputList.get(t));
            }
        }
        tsPath.append("\"");
        tsPath.append(" -c copy -bsf:a aac_adtstoasc -movflags +faststart ");
        tsPath.append(newfilePath);
        return tsPath.toString();
    }

    private static Integer execCommand(String command) {

        System.out.println("execCommand.exec command=" + command);
        try {
            Process process = Runtime.getRuntime().exec(command);
            //获取进程的标准输入流
            final InputStream is1 = process.getInputStream();
            //获取进城的错误流
            final InputStream is2 = process.getErrorStream();
            //启动两个线程，一个线程负责读标准输出流，另一个负责读标准错误流
            readInputStream(is1);
            readInputStream(is2);
            process.waitFor();
            process.destroy();
            System.out.println("-----操作成功" + command + " " + sdf.format(new Date()));
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("-----操作失败" + command);
            return -1;
        }
    }

    private static void readInputStream(InputStream inputStream) {
        new Thread(() -> {
            BufferedReader br1 = new BufferedReader(new InputStreamReader(inputStream));
            try {
                String line1;
                while ((line1 = br1.readLine()) != null) {
                    if (line1 != null) {
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}